package com.ardf.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.ardf.common.EntityConstants;
import com.ardf.entity.Number;
import com.ardf.entity.*;
import com.ardf.entity.dto.*;
import com.ardf.entity.vo.AddOneAthleteVo;
import com.ardf.entity.vo.EditAthleteVo;
import com.ardf.entity.vo.UploadAthleteVo;
import com.ardf.mapper.*;
import com.ardf.service.IAthleteService;
import com.ardf.service.IGroupService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ShiYunHao
 * @since 2025-01-06
 */
@Service
@Slf4j
public class AthleteServiceImpl extends ServiceImpl<AthleteMapper, Athlete> implements IAthleteService {

    private final UnitMapper unitMapper;
    private final GroupMapper groupMapper;
    private final ProjectMapper projectMapper;
    private final AthleteProjectMapper athleteProjectMapper;
    private final TeamMapper teamMapper;
    private final AthleteTeamMapper athleteTeamMapper;
    private final CardMapper cardMapper;
    private final NumberMapper numberMapper;
    private final SigninMapper signinMapper;
    private final GradeMapper gradeMapper;
    private final AthleteMapper athleteMapper;
    private final BatchMapper batchMapper;

    private final DetailsMapper detailsMapper;
    private final ResultMapper resultMapper;
    private final IGroupService groupService;

    public AthleteServiceImpl(UnitMapper unitMapper, GroupMapper groupMapper, ProjectMapper projectMapper,
                              AthleteProjectMapper athleteProjectMapper, TeamMapper teamMapper, BatchMapper batchMapper,
                              AthleteTeamMapper athleteTeamMapper, CardMapper cardMapper, NumberMapper numberMapper,
                              SigninMapper signinMapper, GradeMapper gradeMapper, AthleteMapper athleteMapper,
                              DetailsMapper detailsMapper, ResultMapper resultMapper, IGroupService groupService) {
        this.unitMapper = unitMapper;
        this.groupMapper = groupMapper;
        this.projectMapper = projectMapper;
        this.athleteProjectMapper = athleteProjectMapper;
        this.teamMapper = teamMapper;
        this.athleteTeamMapper = athleteTeamMapper;
        this.cardMapper = cardMapper;
        this.numberMapper = numberMapper;
        this.signinMapper = signinMapper;
        this.gradeMapper = gradeMapper;
        this.athleteMapper = athleteMapper;
        this.batchMapper = batchMapper;
        this.detailsMapper = detailsMapper;
        this.resultMapper = resultMapper;
        this.groupService = groupService;
    }

    @Override
    public void download(HttpServletResponse response) throws IOException {
        // 获取模板文件的输入流
        InputStream templateInputStream = getClass().getResourceAsStream("/templates/downloadTemplate.xlsx");
        if (templateInputStream == null) {
            throw new RuntimeException("模板文件未找到！");
        }

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("模板", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        // 将模板文件写入响应输出流
        try (OutputStream outputStream = response.getOutputStream()) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = templateInputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }
            outputStream.flush();
        } finally {
            templateInputStream.close();
        }
    }

    @Override
    public Page<AthleteTableDto> getAthleteTablePage(Integer pageSize, Integer pageNum, Long competitionId) {
        Page<AthleteTableDto> athleteTablePage = new Page<>(pageNum, pageSize);
        List<Long> unitIds = unitMapper.selectObjs(new LambdaQueryWrapper<Unit>().select(Unit::getId)
                .eq(Unit::getCompetitionId, competitionId)
                .orderByAsc(Unit::getId));
        if (unitIds != null && !unitIds.isEmpty()) {
            Page<Athlete> athletePage = athleteMapper.selectPage(new Page<>(pageNum, pageSize), new LambdaQueryWrapper<Athlete>()
                    .in(Athlete::getUnitId, unitIds)
                    .orderByAsc(Athlete::getUnitId)
                    .orderByAsc(Athlete::getGroupId));
            if (!athletePage.getRecords().isEmpty()) {
                List<AthleteTableDto> records = athletePage.getRecords().stream().map(athlete -> {
                    AthleteTableDto athleteTableDto = new AthleteTableDto();
                    athleteTableDto.setId(athlete.getId());
                    athleteTableDto.setAthleteName(athlete.getName());
                    athleteTableDto.setAthletePhone(athlete.getPhone());
                    athleteTableDto.setIdNumber(athlete.getIdentity());
                    Unit unit = unitMapper.selectById(athlete.getUnitId());
                    athleteTableDto.setUnitName(unit.getName());
                    athleteTableDto.setLeaderName(unit.getLeader());
                    athleteTableDto.setUnitPhone(unit.getPhone());
                    athleteTableDto.setGroupName(groupMapper.selectById(athlete.getGroupId()).getName());
                    AthleteTeam athleteTeam = athleteTeamMapper.selectOne(new LambdaQueryWrapper<AthleteTeam>()
                            .eq(AthleteTeam::getAthleteId, athlete.getId()));
                    if (athleteTeam != null) {
                        athleteTableDto.setSubstitute(athleteTeam.getSubstitute());
                        athleteTableDto.setTeamName(teamMapper.selectById(athleteTeam.getTeamId()).getName());
                    }
                    List<Long> projectIds = athleteProjectMapper.selectObjs(
                            new LambdaQueryWrapper<AthleteProject>().select(AthleteProject::getProjectId)
                                    .eq(AthleteProject::getAthleteId, athlete.getId()));
                    Map<Byte, String> projectCategoryMap = Map.of(EntityConstants.PROJECT_CATEGORY_PERSON, "个人",
                            EntityConstants.PROJECT_CATEGORY_RELAY, "接力");
                    Map<Byte, String> projectFrequencyMap = Map.of(EntityConstants.PROJECT_FREQUENCY_2m, "2m",
                            EntityConstants.PROJECT_FREQUENCY_80m, "80m");
                    Map<Byte, String> projectTypeMap = Map.of(EntityConstants.PROJECT_TYPE_FAST, "快速",
                            EntityConstants.PROJECT_TYPE_MEDIUM, "中距离",
                            EntityConstants.PROJECT_TYPE_SHORT, "短距离",
                            EntityConstants.PROJECT_TYPE_SUNLIGHT, "阳光测向",
                            EntityConstants.PROJECT_TYPE_STANDARD, "标准距离");
                    if (projectIds != null && !projectIds.isEmpty()) {
                        List<String> projectNames = projectIds.stream().map(projectId -> {
                            Project project = projectMapper.selectById(projectId);
                            return projectTypeMap.get(project.getType()) + "-" +
                                    projectFrequencyMap.get(project.getFrequency()) + "-" +
                                    projectCategoryMap.get(project.getCategory());
                        }).toList();
                        athleteTableDto.setProjectNames(projectNames);

                    }
                    return athleteTableDto;
                }).toList();
                athleteTablePage.setRecords(records);
                athleteTablePage.setTotal(athletePage.getTotal());
            } else {
                athleteTablePage.setRecords(null);
                athleteTablePage.setTotal(0L);
            }
        }
        return athleteTablePage;
    }

    @Override
    @Transactional
    public void deleteById(Long athleteId) {
        //选手队伍表
        AthleteTeam athleteTeam = athleteTeamMapper.selectOne(new LambdaQueryWrapper<AthleteTeam>()
                .eq(AthleteTeam::getAthleteId, athleteId));
        Long athleteCount = 0L;
        if (athleteTeam != null) {
            athleteTeamMapper.deleteById(athleteTeam);
            athleteCount = athleteTeamMapper.selectCount(new LambdaQueryWrapper<AthleteTeam>()
                    .eq(AthleteTeam::getTeamId, athleteTeam.getTeamId()));
        }
        //选手指卡
        cardMapper.delete(new LambdaQueryWrapper<Card>()
                .eq(Card::getAthleteId, athleteId));
        //选手补卡
        cardMapper.deleteByAthId(Collections.singletonList(athleteId));

        //选手号码
        numberMapper.delete(new LambdaQueryWrapper<Number>()
                .eq(Number::getAthleteId, athleteId));
        //选手签到
        signinMapper.delete(new LambdaQueryWrapper<Signin>()
                .eq(Signin::getAthleteId, athleteId));
        //选手项目
        athleteProjectMapper.delete(new LambdaQueryWrapper<AthleteProject>()
                .eq(AthleteProject::getAthleteId, athleteId));
        //批次表
        batchMapper.delete(new LambdaQueryWrapper<Batch>()
                .eq(Batch::getAthleteId, athleteId));
        //个人删除
        List<Grade> personGrades = gradeMapper.selectList(new LambdaQueryWrapper<Grade>()
                .eq(Grade::getAthleteId, athleteId)
                .eq(Grade::getTeamId, null));
        List<Long> gradeIds = personGrades.stream().map(Grade::getId).toList();
        if (!personGrades.isEmpty()) {
            //打卡详情
            detailsMapper.delete(new LambdaQueryWrapper<Details>()
                    .in(Details::getGradeId, gradeIds));
            //结果表
            resultMapper.delete(new LambdaQueryWrapper<Result>()
                    .in(Result::getGradeId, gradeIds));
        }
        //成绩信息
        for (Grade grade : personGrades) {
            gradeMapper.deleteById(grade.getId());
        }
        //团队删除
        if (athleteTeam != null) {
            List<Grade> relayGrades = gradeMapper.selectList(new LambdaQueryWrapper<Grade>()
                    .eq(Grade::getTeamId, athleteTeam.getTeamId()));
            for (Grade grade : relayGrades) {
                if (athleteCount == 0L) {
                    //打卡详情
                    detailsMapper.delete(new LambdaQueryWrapper<Details>()
                            .eq(Details::getGradeId, grade.getId()));
                    //结果表
                    resultMapper.delete(new LambdaQueryWrapper<Result>()
                            .eq(Result::getGradeId, grade.getId()));
                    //成绩信息
                    gradeMapper.deleteById(grade.getId());
                } else {
                    if (EntityConstants.ATHLETETEAM_SUBSTITUTE_YES.equals(athleteTeam.getSubstitute())) {
                        //打卡详情
                        detailsMapper.delete(new LambdaQueryWrapper<Details>()
                                .eq(Details::getGradeId, grade.getId()));
                        //结果表
                        resultMapper.delete(new LambdaQueryWrapper<Result>()
                                .eq(Result::getGradeId, grade.getId()));
                        gradeMapper.update(new LambdaUpdateWrapper<Grade>()
                                .set(Grade::getStatus, EntityConstants.GRADE_STATUS_NO)
                                .set(Grade::getAthleteId, null)
                                .eq(Grade::getId, grade.getId()));
                    }
                }
            }
        }
        //选手表
        athleteMapper.deleteById(athleteId);
    }


    @Override
    public void deleteAll(List<Long> ids) {
        for (Long id :ids){
            deleteById(id);
        }
    }

    @Override
    @Transactional
    public void addOne(AddOneAthleteVo addOneAthleteVo) {
        Athlete athlete = new Athlete();
        athlete.setName(addOneAthleteVo.getAthleteName());
        athlete.setPhone(addOneAthleteVo.getPhone());
        athlete.setIdentity(addOneAthleteVo.getIdentity());
        athlete.setAge(calculateAge(addOneAthleteVo.getIdentity()));
        athlete.setGender(addOneAthleteVo.getGender());
        if (addOneAthleteVo.getGroupId() != -1L) {
            athlete.setGroupId(addOneAthleteVo.getGroupId());
        } else {
            GroupIdDto idByAge = groupService.getIdByAge(athlete.getAge(), athlete.getGender(), addOneAthleteVo.getCompetitionId());
            athlete.setGroupId(idByAge.getGroupId());
        }
        if (addOneAthleteVo.getUnitId() == null) {
            athlete.setUnitId(unitMapper.selectOne(new LambdaQueryWrapper<Unit>()
                    .eq(Unit::getName, "无单位")
                    .eq(Unit::getCompetitionId, addOneAthleteVo.getCompetitionId())).getId());
        } else {
            athlete.setUnitId(addOneAthleteVo.getUnitId());
        }
        //选手
        athleteMapper.insert(athlete);
        List<Long> UnitIds = unitMapper.selectObjs(new LambdaQueryWrapper<Unit>().select(Unit::getId)
                .eq(Unit::getCompetitionId, addOneAthleteVo.getCompetitionId()));
        Athlete realAthlete = athleteMapper.selectOne(new LambdaQueryWrapper<Athlete>()
                .eq(Athlete::getIdentity, addOneAthleteVo.getIdentity())
                .in(Athlete::getUnitId, UnitIds));
        //选手号码，签到，指卡
        Number number = new Number();
        number.setAthleteId(realAthlete.getId());
        numberMapper.insert(number);
        Signin signin = new Signin();
        signin.setAthleteId(realAthlete.getId());
        signin.setStatus(EntityConstants.SIGNIN_STATUS_NO);
        signinMapper.insert(signin);
        Card card = new Card();
        card.setAthleteId(realAthlete.getId());
        cardMapper.insert(card);

        List<AthleteProject> athleteProjects = new ArrayList<>();
        List<Grade> grades = new ArrayList<>();
        //个人项目
        for (Long projectId : addOneAthleteVo.getProjectIds()) {
            AthleteProject athleteProject = new AthleteProject();
            athleteProject.setAthleteId(realAthlete.getId());
            athleteProject.setProjectId(projectId);
            athleteProjects.add(athleteProject);
            Grade grade = new Grade();
            grade.setStatus(EntityConstants.GRADE_STATUS_NO);
            grade.setAthleteId(realAthlete.getId());
            grade.setProjectId(projectId);
            grades.add(grade);
        }
        //成绩信息
        gradeMapper.insert(grades);
        if (addOneAthleteVo.getTeamId() != null) {
            AthleteTeam athleteTeam = new AthleteTeam();
            athleteTeam.setSubstitute(EntityConstants.ATHLETETEAM_SUBSTITUTE_YES);
            athleteTeam.setAthleteId(realAthlete.getId());
            athleteTeam.setTeamId(addOneAthleteVo.getTeamId());
            //选手队伍
            athleteTeamMapper.insert(athleteTeam);
            //团队项目
            List<Long> projectIds = gradeMapper.selectObjs(new LambdaQueryWrapper<Grade>().select(Grade::getProjectId)
                    .eq(Grade::getTeamId, addOneAthleteVo.getTeamId()));
            for (Long projectId : projectIds) {
                AthleteProject athleteProject = new AthleteProject();
                athleteProject.setAthleteId(realAthlete.getId());
                athleteProject.setProjectId(projectId);
                athleteProjects.add(athleteProject);
            }
        }
        //选手项目
        athleteProjectMapper.insert(athleteProjects);

    }

    @Override
    public Page<AthleteTableDto> searchAll(Integer pageSize, Integer pageNum, Long competitionId, String searchAll) {
        boolean flag = true;
        Long projectId = null;
        if (searchAll != null) {
            String[] splits = searchAll.split("-");
            Map<String, Byte> typeMap = Map.of("快速", EntityConstants.PROJECT_TYPE_FAST,
                    "中距离", EntityConstants.PROJECT_TYPE_MEDIUM,
                    "短距离", EntityConstants.PROJECT_TYPE_SHORT,
                    "阳光测向", EntityConstants.PROJECT_TYPE_SUNLIGHT,
                    "标准距离", EntityConstants.PROJECT_TYPE_STANDARD);
            Map<String, Byte> frequencyMap = Map.of("2m", EntityConstants.PROJECT_FREQUENCY_2m,
                    "80m", EntityConstants.PROJECT_FREQUENCY_80m);
            Map<String, Byte> categoryMap = Map.of("个人", EntityConstants.PROJECT_CATEGORY_PERSON,
                    "接力", EntityConstants.PROJECT_CATEGORY_RELAY);
            //校验是否是搜索项目名
            Byte type = null;
            Byte frequency = null;
            Byte category = null;
            if (splits.length == 3) {
                type = typeMap.get(splits[0]);
                frequency = frequencyMap.get(splits[1]);
                category = categoryMap.get(splits[2]);
                if (type != null && frequency != null && category != null) {
                    Project project = projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                            .eq(Project::getType, type)
                            .eq(Project::getCategory, category)
                            .eq(Project::getFrequency, frequency)
                            .eq(Project::getCompetitionId, competitionId));
                    if (project != null) {
                        projectId = project.getId();
                        flag = false;
                    }
                }
            }
        }

        Page<AthleteSearchAllDto> page = new Page<>(pageNum, pageSize);
        Page<AthleteSearchAllDto> athleteSearchAllDtos;
        if (flag) {//除了项目名以外的搜索
            athleteSearchAllDtos = athleteMapper.searchAll(page, competitionId, searchAll);
        } else {//搜索项目名
            athleteSearchAllDtos = athleteMapper.searchAllByProjectId(page, projectId);
        }
        List<AthleteTableDto> records = athleteSearchAllDtos.getRecords().stream().map(athleteSearchAllDto -> {
            AthleteTableDto athleteTableDto = new AthleteTableDto();
            BeanUtils.copyProperties(athleteSearchAllDto, athleteTableDto);
            List<String> list = athleteSearchAllDto.getProjects().stream().map(project -> {
                Map<Byte, String> projectType = Map.of(EntityConstants.PROJECT_TYPE_FAST, "快速",
                        EntityConstants.PROJECT_TYPE_MEDIUM, "中距离",
                        EntityConstants.PROJECT_TYPE_SHORT, "短距离",
                        EntityConstants.PROJECT_TYPE_SUNLIGHT, "阳光测向",
                        EntityConstants.PROJECT_TYPE_STANDARD, "标准距离");
                Map<Byte, String> projectFrequency = Map.of(EntityConstants.PROJECT_FREQUENCY_2m, "2m",
                        EntityConstants.PROJECT_FREQUENCY_80m, "80m");
                Map<Byte, String> projectCategory = Map.of(EntityConstants.PROJECT_CATEGORY_PERSON, "个人",
                        EntityConstants.PROJECT_CATEGORY_RELAY, "接力");
                return projectType.get(project.getType()) + "-" + projectFrequency.get(project.getFrequency()) + "-" +
                        projectCategory.get(project.getCategory());
            }).toList();
            athleteTableDto.setProjectNames(list);
            return athleteTableDto;
        }).toList();
        Page<AthleteTableDto> athleteTableDtoPage = new Page<>(pageNum, pageSize);
        athleteTableDtoPage.setRecords(records);
        athleteTableDtoPage.setTotal(page.getTotal());
        athleteTableDtoPage.setCurrent(page.getCurrent());
        return athleteTableDtoPage;
    }

    @Override
    @Transactional
    public void editOne(EditAthleteVo editAthleteVo) {
        Athlete athlete = new Athlete();
        BeanUtils.copyProperties(editAthleteVo, athlete);
        //选手表
        athleteMapper.updateById(athlete);
        List<AthleteProject> athleteProjects = athleteProjectMapper.selectList(new LambdaQueryWrapper<AthleteProject>()
                .eq(AthleteProject::getAthleteId, editAthleteVo.getId()));
        List<Long> personProjectIds = athleteProjects.stream().filter(athleteProject -> {
            Project project = projectMapper.selectById(athleteProject.getProjectId());
            return project.getCategory().equals(EntityConstants.PROJECT_CATEGORY_PERSON);
        }).map(AthleteProject::getProjectId).toList();
        if (editAthleteVo.getProjectIds() == null) {
            editAthleteVo.setProjectIds(List.of());
        }
        List<Long> deleteIds = personProjectIds.stream()
                .filter(personProjectId -> !editAthleteVo.getProjectIds().contains(personProjectId))
                .toList();
        List<AthleteProject> addList = editAthleteVo.getProjectIds().stream()
                .filter(projectId -> !personProjectIds.contains(projectId))
                .map(projectId -> {
                    AthleteProject athleteProject = new AthleteProject();
                    athleteProject.setAthleteId(editAthleteVo.getId());
                    athleteProject.setProjectId(projectId);
                    return athleteProject;
                }).toList();
        List<Batch> addBatchList = editAthleteVo.getProjectIds().stream()
                .filter(projectId -> !personProjectIds.contains(projectId))
                .map(projectId -> {
                    Batch batch = new Batch();
                    batch.setAthleteId(editAthleteVo.getId());
                    batch.setProjectId(projectId);
                    return batch;
                }).toList();
        if (!deleteIds.isEmpty()) {
            //删除选手项目
            athleteProjectMapper.delete(new LambdaQueryWrapper<AthleteProject>()
                    .eq(AthleteProject::getAthleteId, editAthleteVo.getId())
                    .in(AthleteProject::getProjectId, deleteIds));
            //删除选手项目批次
            batchMapper.delete(new LambdaQueryWrapper<Batch>()
                    .eq(Batch::getAthleteId,editAthleteVo.getId())
                    .in(Batch::getProjectId, deleteIds));

        }
        if (!addList.isEmpty()) {
            //添加选手项目
            athleteProjectMapper.insert(addList);
            batchMapper.insert(addBatchList);
        }
        if (editAthleteVo.getSubstitute() != null) {
            //选手队伍表
            athleteTeamMapper.update(new LambdaUpdateWrapper<AthleteTeam>()
                    .set(AthleteTeam::getSubstitute, editAthleteVo.getSubstitute())
                    .eq(AthleteTeam::getAthleteId, editAthleteVo.getId()));
        }
        // 如果修改了

    }

    @Override
    public List<ReplaceCardTableDto> selectAllAthleteByComId(Long competitionId) {
        return athleteMapper.selectAllAthleteByComId(competitionId);
    }

    @Override
    @Transactional
    public void upload(MultipartFile file, Long competitionId, HttpServletResponse response) throws IOException {
        //存储错误的数据
        List<DownloadErrorDto> errList = new ArrayList<>();
        //存储校验后的数据
        List<UploadAthleteVo> uploadAthleteVoList = new ArrayList<>();
        //校验数据
        EasyExcel.read(file.getInputStream(), UploadAthleteVo.class, new PageReadListener<UploadAthleteVo>(uploadAthleteVos -> {
            List<String> identities = new ArrayList<>();
            List<Unit> units = new ArrayList<>();
            List<UnitRelayDto> unitRelayDtos = new ArrayList<>();
            label1:
            for (UploadAthleteVo uploadAthleteVo : uploadAthleteVos) {
                uploadAthleteVoList.add(uploadAthleteVo);
                //去除所有两侧空格
                if (uploadAthleteVo.getAthleteName() != null) {
                    uploadAthleteVo.setAthleteName(uploadAthleteVo.getAthleteName().trim());
                }
                if (uploadAthleteVo.getGender() != null) {
                    uploadAthleteVo.setGender(uploadAthleteVo.getGender().trim());
                }
                if (uploadAthleteVo.getAthletePhone() != null) {
                    uploadAthleteVo.setAthletePhone(uploadAthleteVo.getAthletePhone().trim());
                }
                if (uploadAthleteVo.getIdentity() != null) {
                    uploadAthleteVo.setIdentity(uploadAthleteVo.getIdentity().trim());
                }
                if (uploadAthleteVo.getGroup() != null) {
                    uploadAthleteVo.setGroup(uploadAthleteVo.getGroup().trim());
                }
                if (uploadAthleteVo.getUnit() != null) {
                    uploadAthleteVo.setUnit(uploadAthleteVo.getUnit().trim());
                }
                if (uploadAthleteVo.getLeader() != null) {
                    uploadAthleteVo.setLeader(uploadAthleteVo.getLeader().trim());
                }
                if (uploadAthleteVo.getUnitPhone() != null) {
                    uploadAthleteVo.setUnitPhone(uploadAthleteVo.getUnitPhone().trim());
                }
                if (uploadAthleteVo.getProjects() != null) {
                    uploadAthleteVo.setProjects(uploadAthleteVo.getProjects().trim());
                }
                if (uploadAthleteVo.getRelayTeam() != null) {
                    uploadAthleteVo.setRelayTeam(uploadAthleteVo.getRelayTeam().trim());
                }
                if (uploadAthleteVo.getSubstitute() != null) {
                    uploadAthleteVo.setSubstitute(uploadAthleteVo.getSubstitute().trim());
                }
                //所有数据非空
                if (!StringUtils.hasLength(uploadAthleteVo.getAthleteName())
                        || !StringUtils.hasLength(uploadAthleteVo.getAthletePhone())
                        || !StringUtils.hasLength(uploadAthleteVo.getGender())
                        || !StringUtils.hasLength(uploadAthleteVo.getIdentity())
                        || !StringUtils.hasLength(uploadAthleteVo.getProjects())) {
                    addErrRow(uploadAthleteVo, "必要数据不能为空值", errList);
                    continue;
                }
                //身份证号不能重复
                if (!identities.contains(uploadAthleteVo.getIdentity())) {
                    identities.add(uploadAthleteVo.getIdentity());
                } else {
                    addErrRow(uploadAthleteVo, "身份证号不能重复", errList);
                    continue;
                }

                //验证项目是否存在
                List<Project> projects = projectMapper.selectList(new LambdaQueryWrapper<Project>()
                        .eq(Project::getCompetitionId, competitionId));
                List<String> projectNames = new ArrayList<>();
                Map<Byte, String> projectTypeMap = new HashMap<>();
                projectTypeMap.put(EntityConstants.PROJECT_TYPE_SHORT, "短距离");
                projectTypeMap.put(EntityConstants.PROJECT_TYPE_FAST, "快速");
                projectTypeMap.put(EntityConstants.PROJECT_TYPE_MEDIUM, "中距离");
                projectTypeMap.put(EntityConstants.PROJECT_TYPE_SUNLIGHT, "阳光");
                projectTypeMap.put(EntityConstants.PROJECT_TYPE_STANDARD, "标准距离");
                Map<Byte, String> projectFrequencyMap = new HashMap<>();
                projectFrequencyMap.put(EntityConstants.PROJECT_FREQUENCY_2m, "2m");
                projectFrequencyMap.put(EntityConstants.PROJECT_FREQUENCY_80m, "80m");
                Map<Byte, String> projectCategoryMap = new HashMap<>();
                projectCategoryMap.put(EntityConstants.PROJECT_CATEGORY_RELAY, "接力");
                projectCategoryMap.put(EntityConstants.PROJECT_CATEGORY_PERSON, "个人");
                for (Project project : projects) {
                    String projectName = projectTypeMap.get(project.getType()) + "-" +
                            projectFrequencyMap.get(project.getFrequency()) + "-" +
                            projectCategoryMap.get(project.getCategory());
                    projectNames.add(projectName);
                }
                Set<String> strings = new HashSet<>();
                for (String s : uploadAthleteVo.getProjects().split(",")) {
                    if (!projectNames.contains(s)) {
                        addErrRow(uploadAthleteVo, "比赛没有" + s + "项目", errList);
                        continue label1;
                    }
                    //验证重复项目
                    if (strings.contains(s)) {
                        addErrRow(uploadAthleteVo, "存在重复项目:" + s, errList);
                        continue label1;
                    } else {
                        strings.add(s);
                    }
                }

                //设置年龄
                int age = calculateAge(uploadAthleteVo.getIdentity());
                if (age != -1) {
                    uploadAthleteVo.setAge(age);
                } else {
                    addErrRow(uploadAthleteVo, "身份证号位数不对", errList);
                    continue;
                }

                //验证组别是否存在
                List<String> groupNames = groupMapper.selectObjs(new LambdaQueryWrapper<Group>()
                        .select(Group::getName)
                        .eq(Group::getCompetitionId, competitionId));
                Map<String, Boolean> groupBoolMap = new HashMap<>();
                groupBoolMap.put("M10", groupNames.contains("M10"));
                groupBoolMap.put("M12", groupNames.contains("M12"));
                groupBoolMap.put("M14", groupNames.contains("M14"));
                groupBoolMap.put("M16", groupNames.contains("M16"));
                groupBoolMap.put("M19", groupNames.contains("M19"));
                groupBoolMap.put("M22", groupNames.contains("M22"));
                groupBoolMap.put("M35", groupNames.contains("M35"));
                groupBoolMap.put("M45", groupNames.contains("M45"));
                groupBoolMap.put("M55", groupNames.contains("M55"));
                groupBoolMap.put("M65", groupNames.contains("M65"));
                groupBoolMap.put("W10", groupNames.contains("W10"));
                groupBoolMap.put("W12", groupNames.contains("W12"));
                groupBoolMap.put("W14", groupNames.contains("W14"));
                groupBoolMap.put("W16", groupNames.contains("W16"));
                groupBoolMap.put("W19", groupNames.contains("W19"));
                groupBoolMap.put("W22", groupNames.contains("W22"));
                groupBoolMap.put("W35", groupNames.contains("W35"));
                groupBoolMap.put("W45", groupNames.contains("W45"));
                groupBoolMap.put("W55", groupNames.contains("W55"));
                groupBoolMap.put("W65", groupNames.contains("W65"));
                groupBoolMap.put("公开组", groupNames.contains("公开组"));
                groupBoolMap.put("DXM", groupNames.contains("DXM"));
                groupBoolMap.put("DXW", groupNames.contains("DXW"));
                if ("大学组".equals(uploadAthleteVo.getGroup())) {
                    if ("男".equals(uploadAthleteVo.getGender())) {
                        if (groupBoolMap.get("DXM")) {
                            uploadAthleteVo.setGroup("DXM");
                        } else {
                            addErrRow(uploadAthleteVo, "没有DXM（大学男子组）", errList);
                            continue;
                        }
                    } else {
                        if (groupBoolMap.get("DXW")) {
                            uploadAthleteVo.setGroup("DXW");
                        } else {
                            addErrRow(uploadAthleteVo, "没有DXW（大学女子组）", errList);
                            continue;
                        }
                    }

                } else if (!StringUtils.hasLength(uploadAthleteVo.getGroup())) {
                    if ("男".equals(uploadAthleteVo.getGender())) {
                        if (age <= 10) {
                            if (groupBoolMap.get("M10")) {
                                uploadAthleteVo.setGroup("M10");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M10组", errList);
                                continue;
                            }
                        } else if (age <= 12) {
                            if (groupBoolMap.get("M12")) {
                                uploadAthleteVo.setGroup("M12");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M12组", errList);
                                continue;
                            }
                        } else if (age <= 14) {
                            if (groupBoolMap.get("M14")) {
                                uploadAthleteVo.setGroup("M14");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M14组", errList);
                                continue;
                            }
                        } else if (age <= 16) {
                            if (groupBoolMap.get("M16")) {
                                uploadAthleteVo.setGroup("M16");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M16组", errList);
                                continue;
                            }
                        } else if (age <= 19) {
                            if (groupBoolMap.get("M19")) {
                                uploadAthleteVo.setGroup("M19");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M19组", errList);
                                continue;
                            }
                        } else if (age <= 22) {
                            if (groupBoolMap.get("M22")) {
                                uploadAthleteVo.setGroup("M22");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M22组", errList);
                                continue;
                            }
                        }else if (age <= 35) {
                            if (groupBoolMap.get("M35")) {
                                uploadAthleteVo.setGroup("M35");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M35组", errList);
                                continue;
                            }
                        } else if (age <= 45) {
                            if (groupBoolMap.get("M45")) {
                                uploadAthleteVo.setGroup("M45");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M45组", errList);
                                continue;
                            }
                        } else if (age <= 55) {
                            if (groupBoolMap.get("M55")) {
                                uploadAthleteVo.setGroup("M55");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M55组", errList);
                                continue;
                            }
                        } else {
                            if (groupBoolMap.get("M65")) {
                                uploadAthleteVo.setGroup("M65");
                            } else {
                                addErrRow(uploadAthleteVo, "没有M65组", errList);
                                continue;
                            }
                        }
                    } else {
                        if (age <= 10) {
                            if (groupBoolMap.get("W10")) {
                                uploadAthleteVo.setGroup("W10");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W10组", errList);
                                continue;
                            }
                        } else if (age <= 12) {
                            if (groupBoolMap.get("W12")) {
                                uploadAthleteVo.setGroup("W12");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W12组", errList);
                                continue;
                            }
                        } else if (age <= 14) {
                            if (groupBoolMap.get("W14")) {
                                uploadAthleteVo.setGroup("W14");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W14组", errList);
                                continue;
                            }
                        } else if (age <= 16) {
                            if (groupBoolMap.get("W16")) {
                                uploadAthleteVo.setGroup("W16");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W16组", errList);
                                continue;
                            }
                        } else if (age <= 19) {
                            if (groupBoolMap.get("W19")) {
                                uploadAthleteVo.setGroup("W19");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W19组", errList);
                                continue;
                            }
                        } else if (age <= 22) {
                            if (groupBoolMap.get("W22")) {
                                uploadAthleteVo.setGroup("W22");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W22组", errList);
                                continue;
                            }
                        }else if (age <= 35) {
                            if (groupBoolMap.get("W35")) {
                                uploadAthleteVo.setGroup("W35");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W35组", errList);
                                continue;
                            }
                        } else if (age <= 45) {
                            if (groupBoolMap.get("W45")) {
                                uploadAthleteVo.setGroup("W45");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W45组", errList);
                                continue;
                            }
                        } else if (age <= 55) {
                            if (groupBoolMap.get("W55")) {
                                uploadAthleteVo.setGroup("W55");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W55组", errList);
                                continue;
                            }
                        }else {
                            if (groupBoolMap.get("W65")) {
                                uploadAthleteVo.setGroup("W65");
                            } else {
                                addErrRow(uploadAthleteVo, "没有W65组", errList);
                                continue;
                            }
                        }
                    }
                } else {
                    if ("公开组".equals(uploadAthleteVo.getGroup())) {
                        if (!groupBoolMap.get("公开组")) {
                            addErrRow(uploadAthleteVo, "没有公开组", errList);
                            continue;
                        }
                        if (uploadAthleteVo.getProjects().contains("接力")) {
                            addErrRow(uploadAthleteVo, "公开组不能报接力比赛", errList);
                            continue;
                        }
                    } else {
                        addErrRow(uploadAthleteVo, "没有" + uploadAthleteVo.getGroup() + "组", errList);
                        continue;
                    }

                }

                if (!"公开组".equals(uploadAthleteVo.getGroup())) {
                    //组别不是公开组的参赛单位不能为空
                    if (!StringUtils.hasLength(uploadAthleteVo.getUnit())
                            || !StringUtils.hasLength(uploadAthleteVo.getLeader())
                            || !StringUtils.hasLength(uploadAthleteVo.getUnitPhone())) {
                        addErrRow(uploadAthleteVo, "组别不是公开组的参赛单位不能为空", errList);
                        continue;
                    }
                    //组别不是公开组 参赛单位相同，而单位信息不同
                    Unit unit = new Unit();
                    unit.setName(uploadAthleteVo.getUnit());
                    unit.setPhone(uploadAthleteVo.getUnitPhone());
                    unit.setLeader(uploadAthleteVo.getLeader());
                    if (!units.contains(unit)) {
                        for (Unit unit1 : units) {
                            if (unit1.getName().equals(uploadAthleteVo.getUnit())) {
                                addErrRow(uploadAthleteVo, "参赛单位相同，而单位信息（负责人/单位电话）不同", errList);
                                continue label1;
                            }
                        }
                        units.add(unit);
                    }
                } else {//公开组设置”无单位“一种特殊的单位
                    uploadAthleteVo.setUnit("无单位");
                    uploadAthleteVo.setLeader(null);
                    uploadAthleteVo.setUnitPhone(null);
                }

                if (uploadAthleteVo.getProjects().contains("接力")) {
                    String[] split = uploadAthleteVo.getProjects().split(",");
                    Set<String> stringHashSet = new HashSet<>();
                    for (String s : split) {
                        if (s.contains("接力")) {
                            stringHashSet.add(s);
                        }
                    }
                    if(uploadAthleteVo.getRelayTeam()==null || uploadAthleteVo.getRelayTeam().equals("")){
                        addErrRow(uploadAthleteVo, "该选手的接力队伍不能为空", errList);
                    }

                    //同一单位同一接力队伍信息判断
                    UnitRelayDto unitRelayDto = new UnitRelayDto();
                    unitRelayDto.setUnit(uploadAthleteVo.getUnit());
                    unitRelayDto.setRelay(uploadAthleteVo.getRelayTeam());
                    unitRelayDto.setGroup(uploadAthleteVo.getGroup());
                    unitRelayDto.setRelayProjects(stringHashSet);
                    if (EntityConstants.ATHLETETEAM_SUBSTITUTE_YES.equals(uploadAthleteVo.getSubstitute())) {
                        unitRelayDto.setCount(0);
                    } else {
                        unitRelayDto.setCount(1);
                    }
                    int index = unitRelayDtos.indexOf(unitRelayDto);
                    UnitRelayDto unitRelayDto1 = index == -1 ? null : unitRelayDtos.get(index);
                    if (index != -1) {
                        if (unitRelayDto1.getCount() >= 3 && unitRelayDto.getCount() > 0) {
                            addErrRow(uploadAthleteVo, "同一单位同一接力队伍的非替补人数不能超过3人", errList);
                            continue label1;
                        } else {
                            unitRelayDto1.setCount(unitRelayDto1.getCount() + unitRelayDto.getCount());
                        }
                    } else {
                        for (UnitRelayDto dto : unitRelayDtos) {
                            if (dto.getUnit().equals(unitRelayDto.getUnit()) && dto.getRelay().equals(unitRelayDto.getRelay())) {
                                //同一接力队伍的接力比赛项目不相同
                                if (!dto.getRelayProjects().equals(unitRelayDto.getRelayProjects())) {
                                    addErrRow(uploadAthleteVo, "同一单位同一接力队伍的接力比赛项目不相同", errList);
                                    continue label1;
                                }
                                //同一接力队伍的组别不相同
                                if (!dto.getGroup().equals(unitRelayDto.getGroup())) {
                                    addErrRow(uploadAthleteVo, "同一单位同一接力队伍的组别不相同", errList);
                                    continue label1;
                                }
                            }
                        }
                        unitRelayDtos.add(unitRelayDto);
                    }
                }
            }
        })).sheet().doRead();

        if (errList.isEmpty()) {//校验正确
            //用代理对象调用事务方法会开启事务
            AthleteServiceImpl currentProxy = (AthleteServiceImpl) AopContext.currentProxy();
            //删除数据
            currentProxy.deleteAll(competitionId);
            //处理数据
            currentProxy.saveAll(competitionId, uploadAthleteVoList);
        } else {
            //回写错误数据
            // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("错误数据", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), DownloadErrorDto.class).sheet("表格1").doWrite(errList);
        }
    }

    private void addErrRow(UploadAthleteVo uploadAthleteVo, String reason, List<DownloadErrorDto> errList) {
        DownloadErrorDto downloadErrorDto = new DownloadErrorDto();
        BeanUtils.copyProperties(uploadAthleteVo, downloadErrorDto);
        downloadErrorDto.setErrReason(reason);
        errList.add(downloadErrorDto);
    }

    /**
     * 存储到导入的数据
     */
    @Transactional
    public void saveAll(Long competitionId, List<UploadAthleteVo> uploadAthleteVoList) {
        List<String> unitNames = new ArrayList<>();
        for (UploadAthleteVo uploadAthleteVo : uploadAthleteVoList) {
            Athlete athlete = new Athlete();
            athlete.setName(uploadAthleteVo.getAthleteName());
            athlete.setAge(uploadAthleteVo.getAge());
            athlete.setGender(uploadAthleteVo.getGender());
            athlete.setPhone(uploadAthleteVo.getAthletePhone());
            athlete.setIdentity(uploadAthleteVo.getIdentity());

            if (!unitNames.contains(uploadAthleteVo.getUnit())) {
                unitNames.add(uploadAthleteVo.getUnit());
                Unit unit = new Unit();
                unit.setCompetitionId(competitionId);
                unit.setName(uploadAthleteVo.getUnit());
                unit.setLeader(uploadAthleteVo.getLeader());
                unit.setPhone(uploadAthleteVo.getUnitPhone());
                //存储单位
                unitMapper.insert(unit);
            }
            Long unitId = unitMapper.selectOne(new LambdaQueryWrapper<Unit>()
                    .eq(Unit::getName, uploadAthleteVo.getUnit())
                    .eq(Unit::getCompetitionId, competitionId)).getId();
            athlete.setUnitId(unitId);
            Long groupId = groupMapper.selectOne(new LambdaQueryWrapper<Group>()
                    .eq(Group::getName, uploadAthleteVo.getGroup())
                    .eq(Group::getCompetitionId, competitionId)).getId();
            athlete.setGroupId(groupId);
            //存储运动员
            athleteMapper.insert(athlete);
            Long athleteId = athleteMapper.selectOne(new LambdaQueryWrapper<Athlete>()
                    .eq(Athlete::getIdentity, uploadAthleteVo.getIdentity())
                    .eq(Athlete::getGroupId, groupId)
                    .eq(Athlete::getUnitId, unitId)).getId();
            //指卡，号码，签到
            Card card = new Card();
            card.setAthleteId(athleteId);
            cardMapper.insert(card);
            Number number = new Number();
            number.setAthleteId(athleteId);
            numberMapper.insert(number);
            Signin signin = new Signin();
            signin.setStatus(EntityConstants.SIGNIN_STATUS_NO);
            signin.setAthleteId(athleteId);
            signinMapper.insert(signin);

            HashMap<String, Byte> projectMap = new HashMap<>();
            projectMap.put("短距离", EntityConstants.PROJECT_TYPE_SHORT);
            projectMap.put("快速", EntityConstants.PROJECT_TYPE_FAST);
            projectMap.put("中距离", EntityConstants.PROJECT_TYPE_MEDIUM);
            projectMap.put("阳光", EntityConstants.PROJECT_TYPE_SUNLIGHT);
            projectMap.put("标准距离", EntityConstants.PROJECT_TYPE_STANDARD);
            projectMap.put("2m", EntityConstants.PROJECT_FREQUENCY_2m);
            projectMap.put("80m", EntityConstants.PROJECT_FREQUENCY_80m);
            projectMap.put("接力", EntityConstants.PROJECT_CATEGORY_RELAY);
            projectMap.put("个人", EntityConstants.PROJECT_CATEGORY_PERSON);
            String[] projects = uploadAthleteVo.getProjects().split(",");
            for (String project : projects) {
                String[] split = project.split("-");
                Long projectId = projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                        .eq(Project::getCompetitionId, competitionId)
                        .eq(Project::getType, projectMap.get(split[0]))
                        .eq(Project::getFrequency, projectMap.get(split[1]))
                        .eq(Project::getCategory, projectMap.get(split[2]))).getId();
                AthleteProject athleteProject = new AthleteProject();
                athleteProject.setAthleteId(athleteId);
                athleteProject.setProjectId(projectId);
                //存储运动员项目
                athleteProjectMapper.insert(athleteProject);

            }
            if (uploadAthleteVo.getProjects().contains("接力")) {
                List<String> relayTeamNames = teamMapper.selectObjs(new LambdaQueryWrapper<Team>()
                        .select(Team::getName)
                        .eq(Team::getUnitId, unitId));
                String relayTeam = uploadAthleteVo.getRelayTeam();
                if (!relayTeamNames.contains(relayTeam)) {
                    Team team = new Team();
                    team.setName(relayTeam);
                    team.setUnitId(unitId);
                    //存储接力队伍
                    teamMapper.insert(team);
                }
                Long teamId = teamMapper.selectOne(new LambdaQueryWrapper<Team>()
                        .eq(Team::getName, uploadAthleteVo.getRelayTeam())
                        .eq(Team::getUnitId, unitId)).getId();
                AthleteTeam athleteTeam = new AthleteTeam();
                athleteTeam.setAthleteId(athleteId);
                athleteTeam.setTeamId(teamId);

                if ("是".equals(uploadAthleteVo.getSubstitute()) || uploadAthleteVo.getSubstitute() == "是") {
                    athleteTeam.setSubstitute(EntityConstants.ATHLETETEAM_SUBSTITUTE_YES);
                } else {
                    athleteTeam.setSubstitute(EntityConstants.ATHLETETEAM_SUBSTITUTE_NO);
                }
                //存储运动员接力状态
                athleteTeamMapper.insert(athleteTeam);
            }
        }
        //存储成绩信息表
        List<Project> projectList = projectMapper.selectList(new LambdaQueryWrapper<Project>()
                .eq(Project::getCompetitionId, competitionId));
        for (Project project : projectList) {
            List<Long> athleteIdList = athleteProjectMapper.selectObjs(new LambdaQueryWrapper<AthleteProject>()
                    .select(AthleteProject::getAthleteId)
                    .eq(AthleteProject::getProjectId, project.getId()));
            if (!athleteIdList.isEmpty()) {
                if (project.getCategory().equals(EntityConstants.PROJECT_CATEGORY_PERSON)) {
                    List<Grade> grades = athleteIdList.stream().map(athleteId1 -> {
                        Grade grade = new Grade();
                        grade.setAthleteId(athleteId1);
                        grade.setStatus(EntityConstants.GRADE_STATUS_NO);
                        grade.setProjectId(project.getId());
                        return grade;
                    }).toList();
                    gradeMapper.insert(grades);
                } else {
                    List<Long> teamIdList = athleteTeamMapper.selectObjs(new LambdaQueryWrapper<AthleteTeam>()
                            .select(AthleteTeam::getTeamId)
                            .in(AthleteTeam::getAthleteId, athleteIdList));
                    List<Grade> grades = Set.copyOf(teamIdList).stream().map(teamId -> {
                        Grade grade = new Grade();
                        grade.setStatus(EntityConstants.GRADE_STATUS_NO);
                        grade.setTeamId(teamId);
                        grade.setProjectId(project.getId());
                        return grade;
                    }).toList();
                    gradeMapper.insert(grades);
                }
            }
        }
    }

    /**
     * 导入前删除数据
     */
    @Transactional
    public void deleteAll(Long competitionId) {
        //删除原来的数据
        List<Long> unitIds = unitMapper.selectObjs(new LambdaQueryWrapper<Unit>()
                .select(Unit::getId)
                .eq(Unit::getCompetitionId, competitionId));
        if (!unitIds.isEmpty()) {
            for (Long unitId : unitIds) {
                List<Long> athleteIds = athleteMapper.selectObjs(new LambdaQueryWrapper<Athlete>()
                        .select(Athlete::getId).eq(Athlete::getUnitId, unitId));
                if (!athleteIds.isEmpty()) {
                    for (Long athleteId : athleteIds) {
                        //删除运动员项目
                        athleteProjectMapper.delete(new LambdaQueryWrapper<AthleteProject>()
                                .eq(AthleteProject::getAthleteId, athleteId));
                        //删除运动员接力队伍
                        athleteTeamMapper.delete(new LambdaQueryWrapper<AthleteTeam>()
                                .eq(AthleteTeam::getAthleteId, athleteId));
                        //删除运动员指卡，号码，签到
                        cardMapper.delete(new LambdaQueryWrapper<Card>()
                                .eq(Card::getAthleteId, athleteId));
                        //删除补卡
                        cardMapper.deleteByComId(competitionId);

                        numberMapper.delete(new LambdaQueryWrapper<Number>()
                                .eq(Number::getAthleteId, athleteId));
                        signinMapper.delete(new LambdaQueryWrapper<Signin>()
                                .eq(Signin::getAthleteId, athleteId));
                    }
                    //删除运动员
                    athleteMapper.deleteByIds(athleteIds);
                }
                //删除接力队伍
                teamMapper.delete(new LambdaQueryWrapper<Team>()
                        .eq(Team::getUnitId, unitId));
            }
            //删除单位
            unitMapper.deleteByIds(unitIds);
        }

        List<Long> projectIds = projectMapper.selectObjs(new LambdaQueryWrapper<Project>().select(Project::getId)
                .eq(Project::getCompetitionId, competitionId));
        //批次表
        if (!projectIds.isEmpty()) {
            batchMapper.delete(new LambdaQueryWrapper<Batch>().in(Batch::getProjectId, projectIds));
        }

        List<Long> gradeIds = !projectIds.isEmpty() ?
                gradeMapper.selectObjs(new LambdaQueryWrapper<Grade>().select(Grade::getId)
                        .in(Grade::getProjectId, projectIds)) : List.of();
        if (!gradeIds.isEmpty()) {
            //打卡详情表
            detailsMapper.delete(new LambdaQueryWrapper<Details>().in(Details::getGradeId, gradeIds));
            //结果表
            resultMapper.delete(new LambdaQueryWrapper<Result>().in(Result::getGradeId, gradeIds));
            //删除成绩信息表
            gradeMapper.deleteByIds(gradeIds);
        }


    }

    /**
     * 计算年龄
     */
    private int calculateAge(String idCard) {
        // 获取出生日期部分
        String birthDateStr = "";
        if (idCard.length() == 18) {
            birthDateStr = idCard.substring(6, 14);
        } else if (idCard.length() == 15) {
            // 对于15位的身份证，假设其为19XX年出生
            birthDateStr = "19" + idCard.substring(6, 12);
        } else {
            return -1;
        }
        // 将出生日期字符串转换为 LocalDate
        LocalDate birthDate = LocalDate.parse(birthDateStr, DateTimeFormatter.ofPattern("yyyyMMdd"));

        // 计算年龄
        LocalDate currentDate = LocalDate.now();
        return Period.between(birthDate, currentDate).getYears() + Period.between(birthDate, currentDate).getMonths() / 12;
    }

}
